package com.fast.fastenjoy.base.verify.mapping;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.fast.fastenjoy.base.domain.BaseDomain;
import com.fast.fastenjoy.base.manager.EntityManager;
import com.fast.fastenjoy.base.utils.BeanExUtils;
import com.fast.fastenjoy.base.verify.annotation.VerifyField;
import com.fast.fastenjoy.base.verify.rule.VerifyRule;
import com.fast.fastenjoy.base.verify.rule.VerifyTest;

/**
 * 
 * 字段映射关系验证实体<br/>
 * 
 * <b>修改历史:</b> <br/>
 *  version 1.0.0 2014-5-29 chenliaohua create <br/>
 */
public class VerifyFieldMapping {

	private static final Logger LOG = Logger.getLogger(VerifyFieldMapping.class);
	
	private static Map<String, String> NO_VERIFY_FIELD_MAP = new HashMap<String, String>();
	
	static{
		NO_VERIFY_FIELD_MAP.put(BaseDomain.FIELD_CREATE_BY, BaseDomain.FIELD_CREATE_BY);
		NO_VERIFY_FIELD_MAP.put(BaseDomain.FIELD_CREATE_TIME, BaseDomain.FIELD_CREATE_BY);
		NO_VERIFY_FIELD_MAP.put(BaseDomain.FIELD_UPDATE_BY, BaseDomain.FIELD_CREATE_BY);
		NO_VERIFY_FIELD_MAP.put(BaseDomain.FIELD_UPDATE_TIME, BaseDomain.FIELD_CREATE_BY);
	}
	
	private String fieldName;
	private VerifyField verifyField;
	private VerifyMapping verifyMapping;
	private String columnName;
	private String tableName;
	
	/**
	 * 构建TableColumnMapping
	 * @param obj
	 * @param columnMethods
	 * @return
	 */
	public static Map<String, VerifyFieldMapping> build(VerifyMapping tm){
		
		Map<String, VerifyFieldMapping> resultMap = new HashMap<String, VerifyFieldMapping>();
		
		if(tm != null){
			
			Class<? extends Object> clazz = tm.getObjClass();
			
			Field[] declaredFields = clazz.getDeclaredFields();
			
			if(declaredFields != null && declaredFields.length > 0){
				for(Field f : declaredFields){
					VerifyFieldMapping tcm = build(clazz, f);
					if(tcm != null){
						tcm.verifyMapping = tm;
						tcm.tableName = StringUtils.isEmpty(tcm.tableName) ? tm.getTableName() : tcm.tableName;
						resultMap.put(tcm.fieldName, tcm);
					}
				}
			}
		}
		
		return resultMap;
	}
	
	/**
	 * 构建TableColumnMapping
	 * @param obj
	 * @param method
	 * @return
	 */
	public static VerifyFieldMapping build(Class<? extends Object> clazz, Field field){
		
		if(field == null || clazz == null){
			return null;
		}
		
		VerifyFieldMapping tcm = null;
		
		try{
			
			VerifyField verifyField = field.getAnnotation(VerifyField.class);
			
			if(verifyField == null){
				return null;
			}
			
			String fieldName = field.getName();
			
			// 过滤不需要验证的字段
			if(NO_VERIFY_FIELD_MAP.containsKey(fieldName)){
				return null;
			}
			
			tcm = new VerifyFieldMapping();
			tcm.verifyField = verifyField;
			tcm.fieldName = fieldName;
			tcm.tableName = verifyField.table();
			tcm.columnName = verifyField.columnName();
			
		}catch(Throwable e){
			e.printStackTrace();
			LOG.debug("TableColumnMapping.build " + field.getName() + " error, message:" + e.getMessage());
			return null;
		}
		
		return tcm;
	}
	
	/**
	 * 字段基本校验
	 * @param entityManager
	 * @param tableName
	 * @return
	 */
	public String verify(VerifyObject verifyObject) {
		
		StringBuffer msg = new StringBuffer();
		String fieldValueStr = verifyObject.getFieldStringValue(fieldName);
		
		int length = verifyField.length();
		String title = verifyField.title();
		
		// 非空验证
		if(!verifyField.nullable()){
			if(StringUtils.isEmpty(fieldValueStr)){
				msg.append(title).append("不能为空").append("<br/>");
			}
		}
		
		// 长度校验
		if(msg.length() == 0 && length > 0){
			int len = fieldValueStr.length();
			if(len > length){
				msg.append(title).append(" 长度不能超过").append(length).append("<br/>");
			}
		}
		
		// 字段标识校验
		if(msg.length() == 0){
			msg.append(fieldVerify(fieldValueStr));
		}
		
		// 唯一性校验
		if(msg.length() == 0 && verifyField.unique()){
			msg.append(uniqueVerify(fieldValueStr, verifyObject));
		}
		
		return msg.toString();
	}
	
	/**
	 * 字段标识验证
	 * @return
	 */
	private String fieldVerify(String fieldValue){
		
		VerifyTest columnTest = getVerifyTest();
		
		if(columnTest == null){
			return StringUtils.EMPTY;
		}
		
		StringBuffer msg = new StringBuffer();
		
		String columnDefinitionVerify = columnTest.fieldVerify(verifyField.title(), verifyField.custVerifyRule(), fieldValue);
		
		if(StringUtils.isNotEmpty(columnDefinitionVerify)){
			msg.append(columnDefinitionVerify).append("<br/>");
		}
		
		return msg.toString();
	}
	
	/**
	 * 验证唯一性
	 * @param tcm
	 * @param entityManager
	 * @return
	 */
	private String uniqueVerify(String fieldValue, VerifyObject verifyObject){
		
		StringBuffer msg = new StringBuffer();
		
		// 唯一性校验
		String tableName = getTableName();
		String columnName = getColumnName();
		String title = verifyField.title();
		
		Map<String, VerifyFieldMapping> verifyFields = verifyMapping.getVerifyFields();
		
		Serializable id = verifyObject.getId();
		
		if(StringUtils.isEmpty(fieldValue)){
			msg.append(title).append("不能为空").append("<br/>");
		}else if(StringUtils.isNotEmpty(tableName)){
			
			StringBuffer whereStr = new StringBuffer().append(columnName).append("='").append(fieldValue).append("'");
			
			if(verifyFields.containsKey(BaseDomain.FIELD_ID) && id != null){
				VerifyFieldMapping verifyFieldMapping = verifyFields.get(BaseDomain.FIELD_ID);
				whereStr.append(" and ").append(verifyFieldMapping.getColumnName()).append(" <> ").append(id);
			}
			
			if(checkExists(tableName, whereStr.toString(), verifyObject.getEntityManager())){
				msg.append(title).append("[").append(fieldValue).append("]已存在").append("<br/>");
			}
		}
		
		return msg.toString();
	}
	
	/**
	 * 检查是否存在
	 * @param tableName
	 * @param whereStr
	 * @param entityManager
	 * @return
	 */
	public static boolean checkExists(String tableName, String whereStr, EntityManager<?> entityManager){
		
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("tableName", tableName);
		paramMap.put("whereStr", whereStr);
		
		List<?> checkList = null;
		//TODO entityManager.findBySqlId("acc_common.checkExists", paramMap);
		
		return checkList != null && checkList.size() > 0;
	}
	
	private VerifyFieldMapping(){}
	
	public String getColumnName(){
		
		if(StringUtils.isNotEmpty(columnName)){
			return columnName;
		}
		
		Method method = BeanExUtils.getMethod(verifyMapping.getObjClass(), fieldName);
		
		if(method != null){
			Column annotation = method.getAnnotation(Column.class);
			if(annotation != null){
				columnName = annotation.name();
			}
		}
		
		return columnName;
	}
	
	public String getTableName(){
		
		if(StringUtils.isEmpty(tableName)){
			tableName = verifyMapping.getTableName();
		}
		
		return tableName;
	}
	
	private VerifyTest getVerifyTest(){
		
		VerifyRule verifyRule = verifyField.verifyRule();
		String custVerifyRule = verifyField.custVerifyRule();
		
		if((verifyRule == null || verifyRule == VerifyRule.EMPTY) && StringUtils.isBlank(custVerifyRule)){
			return null;
		}
		
		if(verifyRule != null && verifyRule != VerifyRule.EMPTY){
			return VerifyTest.getColumnTest(verifyRule);
		}
		
		if(StringUtils.isNotBlank(custVerifyRule)){
			return VerifyTest.getOtherColumnTest();
		}
		
		return null;
	}
	
	public String getFieldName() {
		return fieldName;
	}

	@Override
	public String toString() {
		return JSONObject.toJSONString(this);
	}

}
